namespace TuanHA_Combat_Routine
{
    using Styx;
    using Styx.Common;
    using Styx.CommonBot;
    using Styx.CommonBot.POI;
    using Styx.WoWInternals;
    using Styx.WoWInternals.WoWObjects;
    using System;
    using System.Collections.Generic;
    using System.Runtime.CompilerServices;

    internal static class EventHandlers
    {
        internal static bool CombatLogAttached;
        private static string LocalizedLineOfSightError;
        private static HashSet<string> LocalizedShapeshiftErrors;
        private static string LocalizedUnitNotInfrontError;

        internal static void AttachCombatLogEvent()
        {
            if (!CombatLogAttached)
            {
                Lua.get_Events().AttachEvent("COMBAT_LOG_EVENT_UNFILTERED", new LuaEventHandlerDelegate(EventHandlers.HandleCombatLog));
                string filterCode = "return args[4] == UnitGUID('player') and (args[2] == 'SPELL_MISSED' or args[2] == 'RANGE_MISSED' or args[2] == 'SWING_MISSED' or args[2] == 'SPELL_CAST_FAILED')";
                if (!Lua.get_Events().AddFilter("COMBAT_LOG_EVENT_UNFILTERED", filterCode))
                {
                    Logging.Write("ERROR: Could not add combat log event filter! - Performance may be horrible, and things may not work properly!");
                }
                LocalizedLineOfSightError = Lua.GetReturnVal<string>("return SPELL_FAILED_LINE_OF_SIGHT", 0);
                LocalizedUnitNotInfrontError = Lua.GetReturnVal<string>("return SPELL_FAILED_UNIT_NOT_INFRONT", 0);
                LocalizedShapeshiftErrors = new HashSet<string>();
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return ERR_CANT_INTERACT_SHAPESHIFTED", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return ERR_MOUNT_SHAPESHIFTED", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return ERR_NOT_WHILE_SHAPESHIFTED", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return ERR_NO_ITEMS_WHILE_SHAPESHIFTED", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return ERR_SHAPESHIFT_FORM_CANNOT_EQUIP", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return ERR_TAXIPLAYERSHAPESHIFTED", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return SPELL_FAILED_CUSTOM_ERROR_125", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return SPELL_FAILED_CUSTOM_ERROR_99", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return SPELL_FAILED_NOT_SHAPESHIFT", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return SPELL_NOT_SHAPESHIFTED", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return SPELL_NOT_SHAPESHIFTED_NOSPACE", 0));
                LastLineOfSightError = DateTime.MinValue;
                LastUnitNotInfrontError = DateTime.MinValue;
                LastShapeshiftError = DateTime.MinValue;
                Logging.Write("Attached combat log");
                CombatLogAttached = true;
            }
        }

        internal static void DetachCombatLogEvent()
        {
            if (CombatLogAttached)
            {
                Logging.Write("Removed combat log filter");
                Lua.get_Events().RemoveFilter("COMBAT_LOG_EVENT_UNFILTERED");
                Logging.Write("Detached combat log");
                Lua.get_Events().DetachEvent("COMBAT_LOG_EVENT_UNFILTERED", new LuaEventHandlerDelegate(EventHandlers.HandleCombatLog));
                CombatLogAttached = false;
            }
        }

        internal static void HandleCombatLog(object sender, LuaEventArgs args)
        {
            CombatLogEventArgs e = new CombatLogEventArgs(args.EventName, args.FireTimeStamp, args.Args);
            if (e.SourceGuid == StyxWoW.get_Me().Guid)
            {
                switch (e.Event)
                {
                    case "SPELL_CAST_FAILED":
                        Logging.Write("[CombatLog] {0} {1}#{2} failure: '{3}'", new object[] { e.Event, e.Spell.Name, e.SpellId, e.Args[14] });
                        if (e.Args[14].ToString() == LocalizedLineOfSightError)
                        {
                            LastLineOfSightError = DateTime.Now;
                            Logging.Write("[CombatLog] cast fail due to los reported at {0}", new object[] { LastLineOfSightError.ToString("HH:mm:ss.fff") });
                        }
                        return;

                    case "SWING_MISSED":
                        if (e.Args[11].ToString() == "EVADE")
                        {
                            HandleEvadeBuggedMob(args, e);
                            return;
                        }
                        if (e.Args[11].ToString() == "IMMUNE")
                        {
                            WoWUnit destUnit = e.DestUnit;
                            if ((destUnit == null) || destUnit.IsPlayer)
                            {
                                return;
                            }
                            Logging.Write("{0} is immune to Physical spell school", new object[] { destUnit.Name });
                        }
                        return;

                    case "SPELL_MISSED":
                    case "RANGE_MISSED":
                        Logging.Write("[CombatLog] {0} {1}#{2} {3}", new object[] { e.Event, e.Spell.Name, e.SpellId, e.Args[14] });
                        if (e.Args[14].ToString() == "EVADE")
                        {
                            HandleEvadeBuggedMob(args, e);
                            return;
                        }
                        if (e.Args[14].ToString() == "IMMUNE")
                        {
                            WoWUnit unit2 = e.DestUnit;
                            if ((unit2 != null) && !unit2.IsPlayer)
                            {
                                Logging.Write("{0} is immune to {1} spell school", new object[] { unit2.Name, e.SpellSchool });
                            }
                        }
                        return;
                }
                Logging.Write("[CombatLog] filter out this event -- " + e.Event + " - " + e.SourceName + " - " + e.SpellName);
            }
        }

        private static void HandleEvadeBuggedMob(LuaEventArgs args, CombatLogEventArgs e)
        {
            WoWUnit destUnit = e.DestUnit;
            ulong destGuid = e.DestGuid;
            if ((destUnit == null) && (StyxWoW.get_Me().get_CurrentTarget() != null))
            {
                destUnit = StyxWoW.get_Me().get_CurrentTarget();
                destGuid = StyxWoW.get_Me().CurrentTargetGuid;
                Logging.Write("Evade: bugged mob guid:{0}, so assuming current target instead", new object[] { args.Args[7] });
            }
            if (destUnit != null)
            {
                Logging.Write("Mob {0} is evading, [{1}]. Blacklisting it! {2}", new object[] { destUnit.Name, e.Event, destUnit.Guid });
                Blacklist.Add(destUnit.Guid, (BlacklistFlags) BlacklistFlags.Combat, TimeSpan.FromMinutes(30.0), "");
                if (!Blacklist.Contains(destUnit.Guid, (BlacklistFlags) BlacklistFlags.Combat))
                {
                    Logging.Write("error: blacklist does not contain entry for {0} just added {1}", new object[] { destUnit.Name, destUnit.Guid });
                }
                if (BotPoi.get_Current().Guid == destUnit.Guid)
                {
                    BotPoi.Clear("Blacklisted evading mob");
                }
                if (StyxWoW.get_Me().CurrentTargetGuid == destGuid)
                {
                    foreach (WoWUnit unit2 in Targeting.get_Instance().get_TargetList())
                    {
                        if ((unit2.IsAlive && unit2.IsValid) && !Blacklist.Contains((WoWObject) unit2, (BlacklistFlags) BlacklistFlags.Combat))
                        {
                            Logging.Write("Setting target to {0} to get off evade bugged mob!", new object[] { unit2.Name });
                            unit2.Target();
                            return;
                        }
                    }
                    Logging.Write("Bot not targeting other mobs nearby -- simply clearing evade target");
                    StyxWoW.get_Me().ClearTarget();
                }
            }
        }

        private static DateTime LastLineOfSightError
        {
            [CompilerGenerated]
            get
            {
                return <LastLineOfSightError>k__BackingField;
            }
            [CompilerGenerated]
            set
            {
                <LastLineOfSightError>k__BackingField = value;
            }
        }

        private static DateTime LastShapeshiftError
        {
            [CompilerGenerated]
            get
            {
                return <LastShapeshiftError>k__BackingField;
            }
            [CompilerGenerated]
            set
            {
                <LastShapeshiftError>k__BackingField = value;
            }
        }

        private static DateTime LastUnitNotInfrontError
        {
            [CompilerGenerated]
            get
            {
                return <LastUnitNotInfrontError>k__BackingField;
            }
            [CompilerGenerated]
            set
            {
                <LastUnitNotInfrontError>k__BackingField = value;
            }
        }
    }
}

